package com.jdrx.exception;

import com.google.common.collect.Maps;
import com.jdrx.beans.enums.EApiStatus;
import com.jdrx.beans.vo.ResponseVO;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import java.sql.SQLException;
import java.util.Map;

/**
 * 统一错误处理
 */
@ControllerAdvice
@ResponseBody
public class GlobalExceptionHandler {
	private Logger logger = LoggerFactory.getLogger(getClass());

	/**
	 * validate 验证错误handle
	 */
	@ExceptionHandler(value = BindException.class)
	public Object bindExceptionHandler(BindException exception) {
		// 按需重新封装需要返回的错误信息
		Map<String, String> invalidMap = Maps.newHashMap();
		// 解析原错误信息，封装后返回，此处返回非法的字段名称，原始值，错误信息
		if (exception != null && exception.getBindingResult() != null)
			for (FieldError error : exception.getBindingResult().getFieldErrors()) {
				if (invalidMap.get(error.getField()) != null && !"".equals(invalidMap.get(error.getField()))) {
					invalidMap.put(error.getField(),
							invalidMap.get(error.getField()) + "," + error.getDefaultMessage());
				} else {
					invalidMap.put(error.getField(), error.getDefaultMessage());
				}
			}
		ResponseVO vo = new ResponseVO();
		vo.setStatus(EApiStatus.ERR_VALIDATE.getStatus());
		vo.setMessage(EApiStatus.ERR_VALIDATE.getMessage());
		vo.setData(invalidMap);
		logger.error(exception.getMessage(), exception);
		return vo;
	}

	@ExceptionHandler(value = MethodArgumentNotValidException.class)
	public Object methodArgumentNotValidException(MethodArgumentNotValidException exception) {
		// 按需重新封装需要返回的错误信息
		Map<String, String> invalidMap = Maps.newHashMap();
		// 解析原错误信息，封装后返回，此处返回非法的字段名称，原始值，错误信息
		if (exception != null && exception.getBindingResult() != null)
			for (FieldError error : exception.getBindingResult().getFieldErrors()) {
				if (invalidMap.get(error.getField()) != null && !"".equals(invalidMap.get(error.getField()))) {
					invalidMap.put(error.getField(),
							invalidMap.get(error.getField()) + "," + error.getDefaultMessage());
				} else {
					invalidMap.put(error.getField(), error.getDefaultMessage());
				}
			}
		ResponseVO vo = new ResponseVO();
		vo.setStatus(EApiStatus.ERR_VALIDATE.getStatus());
		vo.setMessage(EApiStatus.ERR_VALIDATE.getMessage());
		vo.setData(invalidMap);
		logger.error(exception.getMessage(), exception);
		return vo;
	}

	/**
	 * 统一处理 没有权限的异常
	 */
	@ExceptionHandler(value = NoPermissionException.class)
	public Object noPermissionException(NoPermissionException exception) {

		logger.error(exception.getMessage(), exception);
		ResponseVO vo = new ResponseVO();
		vo.setStatus(EApiStatus.ERR_PERMISSION.getStatus());
		vo.setMessage("系统异常，请联系管理员");
		vo.setData(exception.getMessage());
		return vo;
	}

	/**
	 * 统一处理 没有权限的异常
	 */
	@ExceptionHandler(value = UnsupportedFunctionException.class)
	public Object unsupportedFunctionException(UnsupportedFunctionException exception) {

		logger.error(exception.getMessage(), exception);
		ResponseVO vo = new ResponseVO();
		vo.setStatus(EApiStatus.ERR_FUNCTION.getStatus());
		vo.setMessage("系统异常，请联系管理员");
		vo.setData(exception.getMessage());
		return vo;
	}

	/**
	 * 统一处理 SysException
	 */
	@ExceptionHandler(value = BizException.class)
	public Object bizException(BizException exception) {

		logger.error(exception.getMessage(), exception);
		ResponseVO vo = new ResponseVO();
		vo.setStatus(EApiStatus.ERR_SYS.getStatus());
		vo.setMessage("系统异常，请联系管理员");
		vo.setData(exception.getMessage());
		return vo;
	}

	@ExceptionHandler(value = SQLException.class)
	public Object sqlExceptionHandel(Exception e) {
		logger.error(e.getMessage(), e);
		return getResponseVO(e, "数据库异常");
	}

	/**
	 * 默认异常统一处理 Exception
	 */
	@ExceptionHandler(value = Exception.class)
	public Object exceptionHandel(Exception e) {
		logger.error(e.getMessage(), e);
		return getResponseVO(e, "系统异常");
	}

	private Object getResponseVO(Exception e, String tips) {
		ResponseVO vo = new ResponseVO();
		vo.setStatus(EApiStatus.ERR_SYS.getStatus());
		vo.setMessage(tips + "，请联系管理员");
		vo.setData(e.getMessage());
		logger.error(e.getMessage(), e);
		return vo;
	}
}